//SPDX-FileCopyrightText: Copyright 2025-2025 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package project_triger_api_serv

import (
	"context"
	"time"

	"atomgit.com/openlinksaas-org/api-server/api_common"
	"atomgit.com/openlinksaas-org/api-server/dao"
	"atomgit.com/openlinksaas-org/api-server/dao/triger_dao"
	"atomgit.com/openlinksaas-org/api-server/dao/user_dao"
	"atomgit.com/openlinksaas-org/api-server/triger_impl"
	"atomgit.com/openlinksaas-org/api-server/utils"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/notices/notices_triger"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/project_triger_api"
	"github.com/dchest/uniuri"
	"github.com/google/uuid"
	"go.mongodb.org/mongo-driver/mongo"
)

func (apiImpl *ProjectTrigerApiImpl) ListType(ctx context.Context, req *project_triger_api.ListTypeRequest) (*project_triger_api.ListTypeResponse, error) {
	trigerTypeList := []*project_triger_api.TrigerTypeInfo{}
	for _, runner := range triger_impl.TrigerRunnerList {
		typeInfo := runner.GetTypeInfo()
		trigerTypeList = append(trigerTypeList, typeInfo)
	}
	return &project_triger_api.ListTypeResponse{
		Code:           project_triger_api.ListTypeResponse_CODE_OK,
		TrigerTypeList: trigerTypeList,
	}, nil
}

func (apiImpl *ProjectTrigerApiImpl) GetType(ctx context.Context, req *project_triger_api.GetTypeRequest) (*project_triger_api.GetTypeResponse, error) {
	var matchTypeInfo *project_triger_api.TrigerTypeInfo
	for _, runner := range triger_impl.TrigerRunnerList {
		typeInfo := runner.GetTypeInfo()
		if typeInfo.TypeId == req.TypeId {
			matchTypeInfo = typeInfo
		}
	}
	if matchTypeInfo == nil {
		return &project_triger_api.GetTypeResponse{
			Code: project_triger_api.GetTypeResponse_CODE_NO_TRIGER_TYPE,
			TrigerType: &project_triger_api.TrigerTypeInfo{
				AttrDescGroupList: []*project_triger_api.AttrDescGroup{},
			},
		}, nil
	}
	return &project_triger_api.GetTypeResponse{
		Code:       project_triger_api.GetTypeResponse_CODE_OK,
		TrigerType: matchTypeInfo,
	}, nil
}

func (apiImpl *ProjectTrigerApiImpl) Create(ctx context.Context, req *project_triger_api.CreateRequest) (*project_triger_api.CreateResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_triger_api.CreateResponse{
			Code:   project_triger_api.CreateResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_triger_api.CreateResponse{
			Code:   project_triger_api.CreateResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_triger_api.CreateResponse{
			Code:   project_triger_api.CreateResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &project_triger_api.CreateResponse{
			Code:   project_triger_api.CreateResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !(projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &project_triger_api.CreateResponse{
			Code:   project_triger_api.CreateResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	//检查类型
	var matchTypeInfo *project_triger_api.TrigerTypeInfo
	for _, runner := range triger_impl.TrigerRunnerList {
		typeInfo := runner.GetTypeInfo()
		if typeInfo.TypeId == req.TypeId {
			matchTypeInfo = typeInfo
		}
	}
	if matchTypeInfo == nil {
		return &project_triger_api.CreateResponse{
			Code:   project_triger_api.CreateResponse_CODE_NO_TRIGER_TYPE,
			ErrMsg: "触发器类型不存在",
		}, nil
	}

	nowTime := time.Now().UnixMilli()
	trigerId := uuid.NewString()
	secret := ""
	if matchTypeInfo.HasSecret {
		secret = uniuri.NewLenChars(32, []byte("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"))
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = triger_dao.TrigerInfoDao.Insert(sessCtx, &triger_dao.TrigerInfoDbItem{
			TrigerId:     trigerId,
			ProjectId:    req.ProjectId,
			TrigerName:   req.TrigerName,
			TypeId:       req.TypeId,
			Secret:       secret,
			CreateTime:   nowTime,
			CreateUserId: sessionItem.UserId,
			UpdateTime:   nowTime,
			UpdateUserId: sessionItem.UserId,
			MsgCount:     0,
		})
		if err != nil {
			return nil, err
		}
		return &project_triger_api.CreateResponse{
			Code:     project_triger_api.CreateResponse_CODE_OK,
			TrigerId: trigerId,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_triger.CreateTrigerNotice{
		ProjectId: req.ProjectId,
		TrigerId:  trigerId,
	})
	return ret.(*project_triger_api.CreateResponse), nil
}

func (apiImpl *ProjectTrigerApiImpl) UpdateName(ctx context.Context, req *project_triger_api.UpdateNameRequest) (*project_triger_api.UpdateNameResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_triger_api.UpdateNameResponse{
			Code:   project_triger_api.UpdateNameResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_triger_api.UpdateNameResponse{
			Code:   project_triger_api.UpdateNameResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_triger_api.UpdateNameResponse{
			Code:   project_triger_api.UpdateNameResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &project_triger_api.UpdateNameResponse{
			Code:   project_triger_api.UpdateNameResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !(projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &project_triger_api.UpdateNameResponse{
			Code:   project_triger_api.UpdateNameResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	//检查触发器是否存在
	exist, err := triger_dao.TrigerInfoDao.Exist(ctx, req.ProjectId, req.TrigerId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &project_triger_api.UpdateNameResponse{
			Code:   project_triger_api.UpdateNameResponse_CODE_NO_TRIGER,
			ErrMsg: "触发器不存在",
		}, nil
	}

	nowTime := time.Now().UnixMilli()

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = triger_dao.TrigerInfoDao.UpdateName(sessCtx, req.ProjectId, req.TrigerId, req.TrigerName, sessionItem.UserId, nowTime)
		if err != nil {
			return nil, err
		}
		return &project_triger_api.UpdateNameResponse{
			Code: project_triger_api.UpdateNameResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_triger.UpdateTrigerNotice{
		ProjectId: req.ProjectId,
		TrigerId:  req.TrigerId,
	})
	return ret.(*project_triger_api.UpdateNameResponse), nil
}

func (apiImpl *ProjectTrigerApiImpl) ResetSecret(ctx context.Context, req *project_triger_api.ResetSecretRequest) (*project_triger_api.ResetSecretResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_triger_api.ResetSecretResponse{
			Code:   project_triger_api.ResetSecretResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_triger_api.ResetSecretResponse{
			Code:   project_triger_api.ResetSecretResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_triger_api.ResetSecretResponse{
			Code:   project_triger_api.ResetSecretResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &project_triger_api.ResetSecretResponse{
			Code:   project_triger_api.ResetSecretResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !(projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &project_triger_api.ResetSecretResponse{
			Code:   project_triger_api.ResetSecretResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	//检查触发器是否存在
	trigerItem, err := triger_dao.TrigerInfoDao.Get(ctx, req.ProjectId, req.TrigerId)
	if err != nil {
		return &project_triger_api.ResetSecretResponse{
			Code:   project_triger_api.ResetSecretResponse_CODE_NO_TRIGER,
			ErrMsg: "触发器不存在",
		}, nil
	}

	//检查类型
	var matchTypeInfo *project_triger_api.TrigerTypeInfo
	for _, runner := range triger_impl.TrigerRunnerList {
		typeInfo := runner.GetTypeInfo()
		if typeInfo.TypeId == trigerItem.TypeId {
			matchTypeInfo = typeInfo
		}
	}
	if matchTypeInfo == nil {
		return &project_triger_api.ResetSecretResponse{
			Code:   project_triger_api.ResetSecretResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	nowTime := time.Now().UnixMilli()
	secret := ""
	if matchTypeInfo.HasSecret {
		secret = uniuri.NewLenChars(32, []byte("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"))
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = triger_dao.TrigerInfoDao.UpdateSecret(sessCtx, req.ProjectId, req.TrigerId, secret, sessionItem.UserId, nowTime)
		if err != nil {
			return nil, err
		}
		return &project_triger_api.ResetSecretResponse{
			Code: project_triger_api.ResetSecretResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_triger.UpdateTrigerNotice{
		ProjectId: req.ProjectId,
		TrigerId:  req.TrigerId,
	})
	return ret.(*project_triger_api.ResetSecretResponse), nil
}

func (apiImpl *ProjectTrigerApiImpl) Remove(ctx context.Context, req *project_triger_api.RemoveRequest) (*project_triger_api.RemoveResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_triger_api.RemoveResponse{
			Code:   project_triger_api.RemoveResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_triger_api.RemoveResponse{
			Code:   project_triger_api.RemoveResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_triger_api.RemoveResponse{
			Code:   project_triger_api.RemoveResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &project_triger_api.RemoveResponse{
			Code:   project_triger_api.RemoveResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !(projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &project_triger_api.RemoveResponse{
			Code:   project_triger_api.RemoveResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	//检查触发器是否存在
	exist, err := triger_dao.TrigerInfoDao.Exist(ctx, req.ProjectId, req.TrigerId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &project_triger_api.RemoveResponse{
			Code: project_triger_api.RemoveResponse_CODE_OK,
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = triger_dao.MsgContentDao.RemoveByTriger(sessCtx, req.TrigerId)
		if err != nil {
			return nil, err
		}
		err = triger_dao.TrigerInfoDao.Remove(sessCtx, req.ProjectId, req.TrigerId)
		if err != nil {
			return nil, err
		}
		return &project_triger_api.RemoveResponse{
			Code: project_triger_api.RemoveResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_triger.RemoveTrigerNotice{
		ProjectId: req.ProjectId,
		TrigerId:  req.TrigerId,
	})
	return ret.(*project_triger_api.RemoveResponse), nil
}

func (apiImpl *ProjectTrigerApiImpl) List(ctx context.Context, req *project_triger_api.ListRequest) (*project_triger_api.ListResponse, error) {
	emptyList := []*project_triger_api.TrigerInfo{}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_triger_api.ListResponse{
			Code:       project_triger_api.ListResponse_CODE_WRONG_SESSION,
			ErrMsg:     "会话不存在",
			TrigerList: emptyList,
		}, nil
	}
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_triger_api.ListResponse{
			Code:       project_triger_api.ListResponse_CODE_NO_PROJECT,
			ErrMsg:     "项目不存在",
			TrigerList: emptyList,
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_triger_api.ListResponse{
			Code:       project_triger_api.ListResponse_CODE_NO_PERMISSION,
			ErrMsg:     "没有权限",
			TrigerList: emptyList,
		}, nil
	} else if err != nil {
		return nil, err
	}

	count, err := triger_dao.TrigerInfoDao.Count(ctx, req.ProjectId)
	if err != nil {
		return nil, err
	}
	trigerItemList, err := triger_dao.TrigerInfoDao.List(ctx, req.ProjectId, int64(req.Offset), int64(req.Limit))
	if err != nil {
		return nil, err
	}
	//补全用户信息
	userIdList := []string{}
	for _, trigerItem := range trigerItemList {
		userIdList = append(userIdList, trigerItem.CreateUserId)
		userIdList = append(userIdList, trigerItem.UpdateUserId)
	}
	userItemList, err := user_dao.UserInfoDao.ListById(ctx, userIdList)
	if err != nil {
		return nil, err
	}
	userItemMap := map[string]*user_dao.UserInfoDbItem{}
	for _, userItem := range userItemList {
		userItemMap[userItem.UserId] = userItem
	}

	//生成结果
	isAdmin := false
	if projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin {
		isAdmin = true
	}
	trigerList := []*project_triger_api.TrigerInfo{}
	for _, trigerItem := range trigerItemList {
		triger := trigerItem.ToTrigerInfo()
		createUser, ok := userItemMap[trigerItem.CreateUserId]
		if ok {
			triger.CreateDisplayName = createUser.BasicInfo.DisplayName
			triger.CreateLogoUri = createUser.BasicInfo.LogoUri
		}
		updateUser, ok := userItemMap[trigerItem.UpdateUserId]
		if ok {
			triger.UpdateDisplayName = updateUser.BasicInfo.DisplayName
			triger.UpdateLogoUri = updateUser.BasicInfo.LogoUri
		}
		if !isAdmin {
			triger.Secret = ""
		}
		triger.HasSecret = triger.Secret != ""
		trigerList = append(trigerList, triger)
	}
	return &project_triger_api.ListResponse{
		Code:       project_triger_api.ListResponse_CODE_OK,
		TotalCount: count,
		TrigerList: trigerList,
	}, nil
}

func (apiImpl *ProjectTrigerApiImpl) Get(ctx context.Context, req *project_triger_api.GetRequest) (*project_triger_api.GetResponse, error) {
	emptyInfo := &project_triger_api.TrigerInfo{}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_triger_api.GetResponse{
			Code:   project_triger_api.GetResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
			Triger: emptyInfo,
		}, nil
	}
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_triger_api.GetResponse{
			Code:   project_triger_api.GetResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
			Triger: emptyInfo,
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_triger_api.GetResponse{
			Code:   project_triger_api.GetResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
			Triger: emptyInfo,
		}, nil
	} else if err != nil {
		return nil, err
	}

	trigerItem, err := triger_dao.TrigerInfoDao.Get(ctx, req.ProjectId, req.TrigerId)
	if err != nil {
		return &project_triger_api.GetResponse{
			Code:   project_triger_api.GetResponse_CODE_NO_TRIGER,
			ErrMsg: "触发器不存在",
			Triger: emptyInfo,
		}, nil
	}

	//补全用户信息
	userItemList, err := user_dao.UserInfoDao.ListById(ctx, []string{trigerItem.CreateUserId, trigerItem.UpdateUserId})
	if err != nil {
		return nil, err
	}
	userItemMap := map[string]*user_dao.UserInfoDbItem{}
	for _, userItem := range userItemList {
		userItemMap[userItem.UserId] = userItem
	}
	//生成结果
	isAdmin := false
	if projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin {
		isAdmin = true
	}
	triger := trigerItem.ToTrigerInfo()
	createUser, ok := userItemMap[trigerItem.CreateUserId]
	if ok {
		triger.CreateDisplayName = createUser.BasicInfo.DisplayName
		triger.CreateLogoUri = createUser.BasicInfo.LogoUri
	}
	updateUser, ok := userItemMap[trigerItem.UpdateUserId]
	if ok {
		triger.UpdateDisplayName = updateUser.BasicInfo.DisplayName
		triger.UpdateLogoUri = updateUser.BasicInfo.LogoUri
	}
	if !isAdmin {
		triger.Secret = ""
	}
	triger.HasSecret = triger.Secret != ""

	return &project_triger_api.GetResponse{
		Code:   project_triger_api.GetResponse_CODE_OK,
		Triger: triger,
	}, nil
}
